<template>
  <view class="mxp-side-menu" :style="[cusStyle]">
    <scroll-view class="side-menu" :style="[sideMenuStyle, menuStyle]" :scrollY="barScrollable" :showScrollbar="false" :scrollWithAnimation="true">
      <slot name="menu">
        <view
          v-for="(item, index) in newMenuList"
          :key="index"
          class="menu-item"
          :style="[
            {
              zIndex,
              width: menuWidth,
              height: menuItemHeight,
              background: menuBackground,
              transform: index === activeIndex ? 'scale(1)' : 'scale(0.95)',
            },
            menuItemStyle,
          ]"
          @tap.stop="onClick(index)"
        >
          <view class="line" :style="{ backgroundColor: activeColor, transform: index === activeIndex ? 'scaleY(0.7)' : 'scaleY(0)' }"></view>
          <text class="menu-item-text" :style="newMenuItemStyle(index)">
            {{ item[labelKey] }}
          </text>
        </view>
      </slot>
    </scroll-view>
    <!-- 占位  解决 display: flex; 左侧塌陷 -->
    <view :style="{ width: props.menuWidth }"></view>
    <view class="side-menu-content-box" :style="[contentStyle]">
      <slot></slot>
    </view>
  </view>
</template>

<script lang="ts" setup>
  import { type CSSProperties, type PropType, computed, ref, watch } from 'vue';
  import type { $AllColorStr, $SizeUnitArr4Str, $SizeUnitStr } from '@/mxp-ui/mxp-tool/types/interface';
  import { publicStyeProps } from '../mxp-tool/utils/public-props';
  import { isObject } from '../mxp-tool/utils/verify';
  import mxpGetSysInfoStore from '../mxp-tool/store/mxp-store-sys-info';
  defineOptions({
    name: 'mxp-side-menu',
  });

  const props = defineProps({
    /** 列表数据 */
    zIndex: { type: Number, default: 1 },
    /** 列表数据 */
    menuList: { type: Array as PropType<unknown[]>, default: () => [] },
    /** 当 list 为对象时label的 key */
    labelKey: { type: [Number, String], default: 'label' },
    /** 当前选中项 */
    modelValue: { type: Number, default: 0 },
    /** 顶部的偏移量 */
    offsetTop: { type: String as PropType<$SizeUnitStr | 'auto'>, default: '0px' },
    /** 整个列表的高度，默认auto屏幕高度 */
    height: { type: String as PropType<$SizeUnitStr | 'auto'>, default: 'auto' },
    /** 左边菜单的宽度，默认180px */
    menuWidth: { type: String as PropType<$SizeUnitStr>, default: '180rpx' },
    /** 左边菜单的高度，默认44px */
    menuItemHeight: { type: String as PropType<$SizeUnitStr>, default: '44px' },
    /** 左边列表是否允许滚动 */
    barScrollable: { type: Boolean, default: true },
    /** 背景颜色 */
    menuBackground: { type: String as PropType<$AllColorStr>, default: '#ffffff' },
    /** 圆角 默认：0px 10px 10px 0px */
    menuBorderRadius: { type: String as PropType<$SizeUnitArr4Str>, default: '0px 10px 10px 0px' },
    /** 菜单文字的大小 */
    fontSize: { type: String as PropType<$SizeUnitStr>, default: '16px' },
    /** 菜单未选中状态下的文字颜色 */
    inactiveColor: { type: String as PropType<$AllColorStr>, default: '#333333' },
    /** 菜单选中状态下的文字颜色 */
    activeColor: { type: String as PropType<$AllColorStr>, default: '#223aec' },
    /** 菜单未选中状态下的样式 */
    inactiveBackground: { type: String as PropType<$AllColorStr>, default: '#ffffff' },
    /** 菜单选中状态下的样式 */
    activeBackground: { type: String as PropType<$AllColorStr>, default: '#ffffff' },
    /** 左边列表的自定义样式 */
    menuStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
    /** 左边列表项 每一项 的自定义样式 */
    menuItemStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
    /** 右边区域自定义样式 */
    contentStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
    ...publicStyeProps,
  });
  defineSlots<{
    /** 自定义整个菜单 */
    menu: () => void;
    /** 自定义菜单的内容 */
    default: () => void;
  }>();

  const emits = defineEmits<{
    (e: 'menuClick', index: number): void;
    (e: 'update:modelValue', index: number): void;
  }>();
  const sys = mxpGetSysInfoStore().getSysInfo();
  const activeIndex = ref(props.modelValue);
  const windowHeight = computed(() => sys.value.windowHeight);

  watch(
    () => props.modelValue,
    (index: number) => {
      activeIndex.value = index;
    }
  );

  /** 得到高度 */
  const scrollHeight = computed(() => (isNaN(parseInt(props.height)) ? `${windowHeight.value}px` : props.height));

  /** 得到高度 */
  const newMenuItemStyle = computed(() => (index: number): CSSProperties => {
    if (index === activeIndex.value) {
      return { fontSize: props.fontSize, color: props.activeColor, background: props.activeBackground, ...props.menuItemStyle };
    } else {
      return { fontSize: props.fontSize, color: props.inactiveColor, background: props.inactiveBackground, ...props.menuItemStyle };
    }
  });

  const sideMenuStyle = computed<CSSProperties>(() => {
    return { top: props.offsetTop, width: props.menuWidth, height: scrollHeight.value, background: props.menuBackground, borderRadius: props.menuBorderRadius };
  });

  /** 更新数据  */
  const newMenuList = computed<Record<number | string, unknown>[]>(() => {
    const list: Record<number | string, unknown>[] = [];
    JSON.parse(JSON.stringify(props.menuList)).forEach((item: unknown) => {
      if (isObject(item)) {
        list.push(item as Record<number | string, unknown>);
      } else {
        list.push({ [props.labelKey]: String(item) });
      }
    });
    return list;
  });

  /** 菜单被点击 */
  function onClick(index: number) {
    activeIndex.value = index;
    emits('menuClick', index);
    emits('update:modelValue', index);
  }
</script>

<style scoped lang="scss">
  .mxp-side-menu {
    display: flex;
    flex-flow: row nowrap;

    .side-menu {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
      width: 90px;
      overflow: hidden;
      border-radius: 0 10px 10px 0;

      .menu-item {
        display: flex;
        flex-flow: row nowrap;
        align-items: center;
        justify-content: flex-start;
        padding: 0 8px;
        transition-duration: 0.2s;
        transition-property: transform;
        transform-origin: left center;

        .line {
          width: 2px;
          height: 20px;
          margin-right: 4px;
          transition-duration: 0.2s;
          transition-property: transform;
        }
      }
    }

    .side-menu-content-box {
      flex: 1;
    }
  }
</style>
